import { $each } from '../index';
import { isEmptyObject, isArray, isNullOrEmpty } from "../is";
import { startsWith, endsWith, cloneDeep  } from 'lodash-es';
import { checkConditionStrategy, handleDealCondition } from './useDealCondition.js';
import { createApp, reactive, computed, h } from 'vue';
import dayjs from 'dayjs';
export const conditionVerifyMap = generateConditionVerifyMap();
/**
 * 获取原始字段名相同的数据
 * @param {*} conditionItem 筛选出来的条件格式信息每一项
 * @param {*} conditionData 组件数据
 * @param {*} fieldName 条件格式对应的原始字段名
 * @param {*} chartTag 组件标记
 */
function handleFieldNameData({ conditionItem, fieldName, conditionData, chartTag, seriesData }) {
  // 根据原始名称获取当前需要比对的数据
  const fieldNameData = conditionData[fieldName];
  if (isEmptyObject(conditionItem) || isNullOrEmpty(fieldNameData)) {
    return {};
  }
  // 获取动态条件值数据
  let dynamicConditionData = [];
  const {
    expression: { value = '' },
  } = conditionItem;
  // 只有值存在并且选择的类型为动态值时
  if(value && value.type === 'DYNAMIC' && value.name) {
    dynamicConditionData = conditionData[value.name]
  }
  return generateIndex({ conditionItem, data: fieldNameData, chartTag, dynamicConditionData, seriesData });
}

/**
 * 获取组件满足条件的下标数值
 * @param {*} conditionMap vuex中配置的条件格式表达式map: { key: value}
 * @param {*} key 对应条件表达式中的key
 * @param {*} data 当前过滤的数据数组
 * @returns style
 */
function generateIndex(options) {
  const { conditionItem, data, dynamicConditionData, chartTag, seriesData } = options;
  // 将数据进行排序
  let sortResult = [];
  const {
    expression: { conditionType = '' },
  } = conditionItem;
  if (conditionType && ['TOP_N', 'LITTLE_N'].includes(conditionType)) {
    sortResult = handleTimeStampSort(cloneDeep(data));
  }
  // 获取最晚N和最早N数据
  const { topNText, littleNText } = handleTimeStampData(conditionItem, sortResult);
  let indexArray = [];
  for (let j = 0; j < data.length; j++) {
    if (data[j]?.value && isArray(data[j].value) && chartTag.includes('radar')) {
      // 判断数据是否是数组并且是雷达图2，雷达图的数据为数组
      data[j].value.forEach((valueItem, valueIndex) => {
        const { verify = false } = handleVerifyText(conditionItem, valueItem, {
          topNText,
          littleNText,
          dynamicConditionText: dynamicConditionData && dynamicConditionData[j]?.value[valueIndex] || '',
        });
        if (verify) {
          if (chartTag === 'radarTwo') {
            indexArray.push(valueIndex + data[j].value.length * j);
          } else if(chartTag === 'radar') {
            //除雷达图2，其他雷达图单独处理
            indexArray = seriesData.map((item,index)=>{
              if(item.name === data[j].name) {
                return index;
              }
            })
          } else {
            indexArray.push(j);
          }
        }
      });
    } else {
      // 校验表达式
      const { verify = false } = handleVerifyText(conditionItem, data[j]?.value, {
        topNText,
        littleNText,
        dynamicConditionText: dynamicConditionData && dynamicConditionData[j]?.value || '', // 条件项对应匹配值
      });
      if (verify) {
        indexArray.push(j);
      }
    }
  }
  return indexArray;
}
/**
 * 校验文本
 * @param {*} param0 表达式
 * @param {*} text 当前过滤的text文本
 * @returns 校验结果及需要返回的值
 */
function handleVerifyText({ expression, style }, text, { topNText, littleNText, dynamicConditionText }) {
  if (!expression) {
    return {};
  }
  const { value = '', nodeColumnType = '', conditionType = '', dateFormat = '' } = expression;
  // 由于动态值是多个需要一一进行比较，导致数据会一直变化触发render函数，对数据克隆切断关系
  const verifyValue = cloneDeep(value);
  // 只有值存在并且选择的类型为动态值时
  if(verifyValue && verifyValue.type === 'DYNAMIC' && dynamicConditionText) {
    verifyValue.value = dynamicConditionText;
  }
  let finalNodeColumnType = nodeColumnType;
  // 兼容外部数据源数据类型
  switch (nodeColumnType) {
    case 'STRING':
      finalNodeColumnType = 'TEXT';
      break;
    case 'DATE':
      finalNodeColumnType = 'TIMESTAMP';
      break;
    case 'NUMBER':
      finalNodeColumnType = 'DECIMAL';
      break;
  }
  const verifyFn = conditionVerifyMap[`${finalNodeColumnType}|${conditionType}`];
  let verify = false;
  let formatText = text;
  if (isArray(text)) {
    text.forEach((item) => {
      formatText = item;
      if (finalNodeColumnType === 'TIMESTAMP') {
        const splitText = text.split(' ');
        let result = '';
        if(splitText[1]) {
          // 增加时分秒数据转换
          result = [splitText[0].replace(/[^\d]/g, '-').slice(0, -1),splitText[1].replace(/[^\d]/g, ':').slice(0, -1)].join(' ')
        } else {
          result = splitText[0].replace(/[^\d]/g, '-').slice(0, -1)
        }
        formatText = dayjs(result).format(dateFormat);
      }
      const verifyItem = verifyFn ? verifyFn(formatText, verifyValue) : false;
      if (verifyItem) {
        verify = true;
      }
    });
    return { verify };
  }
  if (finalNodeColumnType === 'TIMESTAMP') {
    const splitText = text.split(' ');
    let result = '';
    if(splitText[1]) {
      // 增加时分秒数据转换
      result = [splitText[0].replace(/[^\d]/g, '-').slice(0, -1),splitText[1].replace(/[^\d]/g, ':').slice(0, -1)].join(' ')
    } else {
      result = splitText[0].replace(/[^\d]/g, '-').slice(0, -1)
    }
    formatText = dayjs(result).format(dateFormat);
  }
  verify = verifyFn ? verifyFn(formatText, verifyValue, { topNText, littleNText }) : false;
  return { verify, style };
}

/**
 * 校验方法
 * @returns 生成
 */
function generateConditionVerifyMap() {
  function isNull(text) {
    return isNullOrEmpty(text);
  }

  function isNotNull(text) {
    return !isNullOrEmpty(text);
  }

  function contain(text, value) {
    let _text = text || '';
    return _text.includes(value);
  }

  function notContain(text, value) {
    let _text = text || '';
    return !_text.includes(value);
  }

  function preIs(text, value) {
    let _text = text || '';
    return startsWith(_text, value);
  }

  function preNotIs(text, value) {
    let _text = text || '';
    return !startsWith(_text, value);
  }

  function endIs(text, value) {
    let _text = text || '';
    return endsWith(_text, value);
  }

  function endNotIs(text, value) {
    let _text = text || '';
    return !endsWith(_text, value);
  }

  function gt(text, value) {
    const { value: val } = value;
    return text > val;
  }

  function lt(text, value) {
    const { value: val } = value;
    return text < val;
  }

  function ge(text, value) {
    const { value: val } = value;
    return text >= val;
  }

  function le(text, value) {
    const { value: val } = value;
    return text <= val;
  }

  function between(text, value) {
    const {
      max: { value: maxValue, type: maxType },
      min: { value: minValue, type: minType },
    } = value;
    const calculationMap = { LE: le, LT: lt, GE: ge, GT: gt };
    return (
      calculationMap[maxType](text, { value: maxValue }) &&
      calculationMap[minType](text, { value: minValue })
    );
  }

  function notBetween(text, value) {
    const {
      min: { value: minValue, type: minType },
      max: { value: maxValue, type: maxType },
    } = value;
    const calculationMap = { LE: gt, LT: ge, GE: lt, GT: le };
    return (
      calculationMap[maxType](text, { value: maxValue }) ||
      calculationMap[minType](text, { value: minValue })
    );
  }

  function equals(text, value) {
    return text === value;
  }

  function notEquals(text, value) {
    return text !== value;
  }

  function timeGt(text, value) {
    return gt(text, { value });
  }

  function timeLt(text, value) {
    return lt(text, { value });
  }

  function timeGe(text, value) {
    return ge(text, { value });
  }

  function timeLe(text, value) {
    return le(text, { value });
  }

  function topN(text, _value, { topNText }) {
    return ge(text, { value: topNText });
  }

  function littleN(text, _value, { littleNText }) {
    return le(text, { value: littleNText });
  }

  return {
    'TEXT|IS_NULL': isNull,
    'TEXT|IS_NOT_NULL': isNotNull,
    'TEXT|CONTAIN': contain,
    'TEXT|NOT_CONTAIN': notContain,
    'TEXT|PRE_IS': preIs,
    'TEXT|PRE_NOT_IS': preNotIs,
    'TEXT|END_IS': endIs,
    'TEXT|END_NOT_IS': endNotIs,
    'TEXT|EQUALS': equals,
    'TEXT|NOT_EQUALS': notEquals,
    'DECIMAL|BETWEEN': between,
    'DECIMAL|NOT_BETWEEN': notBetween,
    'DECIMAL|EQUALS': equals,
    'DECIMAL|NOT_EQUALS': notEquals,
    'DECIMAL|GT': gt,
    'DECIMAL|LT': lt,
    'DECIMAL|GE': ge,
    'DECIMAL|LE': le,
    'DECIMAL|IS_NULL': isNull,
    'DECIMAL|IS_NOT_NULL': isNotNull,
    'TIMESTAMP|BETWEEN': between,
    'TIMESTAMP|NOT_BETWEEN': notBetween,
    'TIMESTAMP|EQUALS': equals,
    'TIMESTAMP|NOT_EQUALS': notEquals,
    'TIMESTAMP|GT': timeGt,
    'TIMESTAMP|LT': timeLt,
    'TIMESTAMP|GE': timeGe,
    'TIMESTAMP|LE': timeLe,
    'TIMESTAMP|IS_NULL': isNull,
    'TIMESTAMP|IS_NOT_NULL': isNotNull,
    'TIMESTAMP|TOP_N': topN,
    'TIMESTAMP|LITTLE_N': littleN,
  };
}

/**
 * 获取表格条件格式样式
 * @param {*} conditionMap vuex中配置的条件格式表达式map: { key: value}
 * @param {*} key 对应条件表达式中的key
 * @param {*} text 当前过滤的text文本
 * @param {*} resultSortData 当前排序后的数据
 * @param {*} conditionData 条件格式中保存的值，包含条件项数据
 * @param {*} rowIdx 当前行数
 * @returns style
 */
export function generateStyle({conditionMap, key, text, resultSortData, conditionData, rowIdx}) {
  if (isEmptyObject(conditionMap) || isEmptyObject(conditionMap[key])) {
    return {};
  }
  let style = {};
  // 获取动态条件值数据
  let dynamicConditionData = [];
  const conditions = conditionMap[key];
  // 倒着算，同一个数据，最后设置的覆盖最高设置的
  for (let i = conditions.length - 1; i >= 0; i--) {
    const {
      expression: { value = '' },
    } = conditions[i];
    // 只有值存在并且选择的类型为动态值时
    if(value && value.type === 'DYNAMIC' && value.name) {
      dynamicConditionData = conditionData[value.name]
    }
    // 校验时间类型的最晚和最早
    const { topNText, littleNText } = handleTimeStampData(conditions[i], resultSortData);
    // 校验表达式
    const { verify, style: styleOptions } = handleVerifyText(conditions[i], text, {
      topNText,
      littleNText,
      dynamicConditionText: dynamicConditionData && dynamicConditionData[rowIdx]?.value || '', // 条件项对应匹配值,
    });
    if (verify) {
      style = styleOptions;
      break;
    }
  }

  return style;
}

/**
 * 条件格式变化
 * @param {*} options 筛选出来的条件格式变量集合
 * @param {*} conditionOptions 收集的条件格式信息
 */
export function handleConditionExtend(options, conditionOptions) {
  const {
    conditionData,
    isExistLegend,
    seriesData,
    legendFieldName,
    chartTag = 'default',
    fieldNameChainMap,
  } = options;
  $each(conditionOptions, (conditionItem, fieldName) => {
    let currentLegend = false; // 当前原始字段名称为颜色度量时
    // 当前为颜色维度,颜色维度最多一个
    if (legendFieldName === fieldName) {
      currentLegend = true;
    }
    $each(conditionItem, (option) => {
      const indexArrar = handleFieldNameData({
        conditionItem: option,
        fieldName,
        conditionData,
        chartTag,
        seriesData,
      });
      const { chartType, generateOption, style } = option;
      /*
       * 1.雷达2：除了雷达图2其他的雷达图不配置条件格式
       * 2.其他组件
       * 3.条形图
       * 4.气泡/飞线地图
       * 5.散点图
       */
      const type = checkConditionStrategy(chartTag);
      seriesData.length && handleDealCondition[type]({
        seriesData,
        indexArrar,
        fieldName,
        isExistLegend,
        generateOption,
        style,
        currentLegend,
        fieldNameChainMap,
        chartType,
        chartTag,
      });
    });
  });
}
// 时间类型数据排序
function handleTimeStampSort(data) {
  const sortResult = data.sort((a, b) => {
    // 这里假设时间类型字段格式一致，且月，日，时分秒长度均为两位
    let aValue =  (a.value ?? '0').replace(/[^\d]/g, '')
    let bValue = (b.value ?? '0').replace(/[^\d]/g, '')
    // 这里之前使用dayjs格式化进行准确比较多，但是在数据量比较多时，会造成较大的卡顿
    if(aValue > bValue) {
      return 1;
    } else if(aValue < bValue) {
      return -1;
    } else {
      return 0;
    }
  });
  return sortResult;
}
// 处理时间类型数据获取最晚或最早N个数据
function handleTimeStampData(conditionItem, sortResult) {
  const {
    expression: { conditionType = '', value = '', dateFormat = '' },
  } = conditionItem;
  let topNText;
  let littleNText;
  // 时间类型数据获取最晚或最早N个数据
  if (conditionType && ['TOP_N', 'LITTLE_N'].includes(conditionType)) {
    // 最晚N个
    if (conditionType === 'TOP_N') {
      topNText =
        value && sortResult &&
        sortResult.slice(-value)[0].value &&
        dayjs(sortResult.slice(-value)[0].value.replace(/[^\d]/g, '-').slice(0, -1)).format(
          dateFormat,
        );
    }
    // 最早N个
    if (conditionType === 'LITTLE_N') {
      const nText = value && sortResult.slice(0, value);
      littleNText =
        nText &&
        nText[nText.length - 1].value &&
        dayjs(nText[nText.length - 1].value.replace(/[^\d]/g, '-').slice(0, -1)).format(dateFormat);
    }
  }
  return {
    topNText,
    littleNText,
  };
}
// 表格类组件自定义渲染
export function handleCustomRender(styles, text, chartType = 'scroll') {
  const { color, backgroundColor, icon, iconColor } = styles;
  const background = chartType === 'scroll' ? backgroundColor : '';
  const padding = chartType === 'scroll' ? '0 10px' : '0 10px 0 0';
  const Profile = createApp({
    setup() {
      // 样式
      const style = reactive({
        color,
        backgroundColor: background,
        display: 'flex',
        alignItems: 'center',
        width: '100%',
        padding,
      });
      const textStyle = reactive({
        display: 'inline-block',
        whiteSpace: 'nowrap',
        textOverflow: 'ellipsis',
        overflow: 'hidden',
        flex: '1',
        minWidth: '0',
      });
      // icon样式
      const iconInfo = reactive({
        icon,
        iconColor,
      });
      const iconName = computed(() => {
        return `#icon-${iconInfo.icon}`;
      });
      const iconStyle = computed(() => {
        return {
          width: '14px',
          height: '14px',
          verticalAlign: 'middle',
          fill: 'currentColor',
          overflow: 'hidden',
          display: 'inline-block',
          outline: 'none',
          marginLeft: '10px',
          color: iconInfo.iconColor,
        };
      });
      return {
        style,
        textStyle,
        iconInfo,
        text,
        iconStyle,
        iconName,
      };
    },
    render({ style, textStyle, iconInfo, text, iconStyle, iconName }) {
      if (iconInfo.icon && iconInfo.icon !== 'custom-null') {
        return h('span', { style }, [
          h('span', { style: textStyle, title: text }, text),
          h('svg', { class: 'al-icon', 'aria-hidden': true, style: iconStyle }, [
            h('use', { 'xlink:href': iconName }),
          ]),
        ]);
      }
      return h('span', { style }, [h('span', { style: textStyle, title: text }, text)]);
    },
  });
  //挂载父元素
  const parent = document.createElement('template');
  return Profile.mount(parent)?.$el.outerHTML;
}

// 处理轮播表条件格式
export function handleScrollTableConditions(componentAttribute) {
  const { conditionOptions, config, timeStampData } = componentAttribute;
  const { data, sourceFields, realData, header } = config;
  if (!realData?.length) {
    return;
  }
  $each(data, (rowData, rowIdx) => {
    $each(rowData, (row, cloIdx) => {
      // 设置联动的维度名字
      const dimensionName = header[cloIdx];
      const name = realData[rowIdx][dimensionName];
      const resultSortData =
        timeStampData?.[dimensionName] && handleTimeStampSort(timeStampData[dimensionName]);
      // 校验条件格式，返回所设置的样式
      const style = generateStyle({conditionMap: conditionOptions, key: sourceFields[cloIdx], text: name, resultSortData});
      Object.keys(style).length && (rowData[cloIdx] = handleCustomRender(style, row));
    });
  });
}

// 处理排名轮播表条件格式
export function handleRankingScrollTableConditions(componentAttribute) {
  const { conditionOptions, config, timeStampData } = componentAttribute;
  const { data, sourceFields, realData, header } = config;
  if (!realData?.length) {
    return;
  }
  $each(data, (rowData, rowIdx) => {
    $each(rowData, (_row, cloIdx) => {
      // 设置联动的维度名字
      const dimensionName = header[cloIdx];
      const name = realData[rowIdx][dimensionName];
      //保存name的原始数据
      const realName = realData[rowIdx][header.name];
      const resultSortData =
        timeStampData?.[dimensionName] && handleTimeStampSort(timeStampData[dimensionName]);
      // 校验条件格式，返回所设置的样式
      const style = generateStyle({conditionMap: conditionOptions, key: sourceFields[cloIdx], text: name, resultSortData});
      if (Object.keys(style).length) {
        rowData['name'] = handleCustomRender(style, realName, 'rankingScroll');
        rowData.backgroundColor = style.backgroundColor;
      }
    });
  });
}

// 明细表条件格式处理
export function handleDetailTableConditions(componentAttribute) {
  const tableConditionSetMap = {};
  const { conditionOptions, config, timeStampData } = componentAttribute;
  const { data, sourceFields, realData, conditionData } = config;
  if (!data?.length) {
    return;
  }
  $each(data, (rowData, rowIdx) => {
    $each(rowData, (row, cloIdx) => {
      const name = realData[rowIdx][cloIdx];
      const resultSortData =
        timeStampData?.[cloIdx] && handleTimeStampSort(timeStampData[cloIdx]);
      // 校验条件格式，返回所设置的样式
      const style = generateStyle({conditionMap: conditionOptions, key:sourceFields[cloIdx], text: name, resultSortData, conditionData, rowIdx});
      if(tableConditionSetMap[cloIdx]) {
        tableConditionSetMap[cloIdx].push(style)
      } else {
        tableConditionSetMap[cloIdx] = [style]
      }
    });
  });
  return tableConditionSetMap;
}
